package org.fing.edu.uy.esbadp.core.entity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class GenericTreeNode<T> implements Serializable {

	private static final long serialVersionUID = 5122110100870575233L;
	
	private T data;
    private List<GenericTreeNode<T>> children;    
    private long index;

    public GenericTreeNode() {
        super();
        children = new ArrayList<GenericTreeNode<T>>();
        index = -1;
    }

    public GenericTreeNode(T data) {
        this();
        setData(data);
    }

    public List<GenericTreeNode<T>> getChildren() {
        return this.children;
    }

    public int getNumberOfChildren() {
        return getChildren().size();
    }

    public boolean hasChildren() {
        return (getNumberOfChildren() > 0);
    }

    public void setChildren(List<GenericTreeNode<T>> children) {
        this.children = children;
    }

    public void addChild(GenericTreeNode<T> child) {
        children.add(child);
    }

    public void addChildAt(int index, GenericTreeNode<T> child) throws IndexOutOfBoundsException {
        children.add(index, child);
    }

    public void removeChildren() {
        this.children = new ArrayList<GenericTreeNode<T>>();
    }

    public void removeChildAt(int index) throws IndexOutOfBoundsException {
        children.remove(index);
    }

    public GenericTreeNode<T> getChildAt(int index) throws IndexOutOfBoundsException {
        return children.get(index);
    }

    public T getData() {
        return this.data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public boolean equals(GenericTreeNode<T> node) {
        return node.getData().equals(getData());
    }

    public int hashCode() {
        return getData().hashCode();
    }

	public long getIndex() {
		return index;
	}

	public void setIndex(long index) {
		this.index = index;
	}
    
	@Override
	public String toString(){
		StringBuilder builder = new StringBuilder();
		return toString(0, builder);
	}
	
    @Override
    public GenericTreeNode<T> clone(){
    	GenericTreeNode<T> clone = new GenericTreeNode<T>();
    	clone.data = this.data;        
    	clone.children = new ArrayList<GenericTreeNode<T>>(this.children.size());
    	for(GenericTreeNode<T> aux: this.children){
    		clone.children.add(aux.clone());
    	}
    	return clone;
    }
      
    
    private String toString(int level,StringBuilder sb ){    
    	for(int i = 0 ; i<level;i++ ){
    		sb.append("\t");    		
    	}
    	
    	if(getData()!=null){
	    	//imprimo el nodo en el que estoy
	    	sb.append(getData().toString());  	    	
    	}else{
    		sb.append("ERROR TREE NODE DATA IS NULL");
    	}
    	sb.append("\n");
    	
    	for(int i = 0 ; i<level;i++ ){
    		sb.append("\t");    		
    	}
    	
    	sb.append("Index: ");
    	sb.append(this.index);
    	sb.append("\n");
    	
    	for (GenericTreeNode<T> node : getChildren()) {    		
    		node.toString(level + 1,sb);    		
        }
    	return sb.toString();
    }
    
}
